/*---------------------------------------------------------------------
 * File name: hal_pwm.h
 *
 * Copyright (c) <2020-2022>, <ChenLong>
 *
 * All rights reserved.
 *
 * Author: ChenLong
 * Email: worldlong@foxmail.com
 *--------------------------------------------------------------------*/
#pragma once
/*
*/
#include "hal_timer.h"
/*
*/
#define HPWM_MODE_BITS    2
#define HPWM_CH_BITS      5
#define HPWM_OCP_BITS     1
#define HPWM_OCIDS_BITS   1
#define HPWM_OCNP_BITS    1
#define HPWM_OCNIDS_BITS  1
#define HPWM_CAPTRUE_BITS 1
/*
*/
#define HPWM_MODE_POS    (0)
#define HPWM_CH_POS      (HPWM_MODE_POS + HPWM_MODE_BITS)
#define HPWM_OCP_POS     (HPWM_CH_POS + HPWM_CH_BITS)
#define HPWM_OCIDS_POS   (HPWM_OCP_POS + HPWM_OCP_BITS)
#define HPWM_OCNP_POS    (HPWM_OCIDS_POS + HPWM_OCIDS_BITS)
#define HPWM_OCNIDS_POS  (HPWM_OCNP_POS + HPWM_OCNP_BITS)
#define HPWM_CAPTRUE_POS (HPWM_OCNIDS_POS + HPWM_OCNIDS_BITS)
/*
*/
#define HPWM_MODE_MASK    ((1<<HPWM_MODE_BITS) - 1)
#define HPWM_CH_MASK      ((1<<HPWM_CH_BITS) - 1)
#define HPWM_OCP_MASK     ((1<<HPWM_OCP_BITS) - 1)
#define HPWM_OCIDS_MASK   ((1<<HPWM_OCIDS_BITS) - 1)
#define HPWM_OCNP_MASK    ((1<<HPWM_OCNP_BITS) - 1)
#define HPWM_OCNIDS_MASK  ((1<<HPWM_OCNIDS_BITS) - 1)
#define HPWM_CAPTRUE_MASK ((1<<HPWM_CAPTRUE_BITS) - 1)
#define HPWM_CFG_MASK     ((HPWM_MODE_MASK << HPWM_MODE_POS) |\
                           (HPWM_CH_MASK << HPWM_CH_POS) |\
                           (HPWM_OCP_MASK << HPWM_OCP_POS) |\
                           (HPWM_OCIDS_MASK << HPWM_OCIDS_POS) |\
                           (HPWM_OCNP_MASK << HPWM_OCNP_POS) |\
                           (HPWM_OCNIDS_MASK << HPWM_OCNIDS_POS) |\
                           (HPWM_CAPTRUE_MASK << HPWM_CAPTRUE_POS))

/*
*/
#define HPWM_MODE_0      (0 << HPWM_MODE_POS)
#define HPWM_MODE_1      (1 << HPWM_MODE_POS)
#define HPWM_MODE_2      (2 << HPWM_MODE_POS)
#define HPWM_MODE(param) (HPWM_MODE_##param >> HPWM_MODE_POS)
/*
*/
#define HPWM_CH_0  (0x01 << HPWM_CH_POS)
#define HPWM_CH_1  (0x02 << HPWM_CH_POS)
#define HPWM_CH_2  (0x04 << HPWM_CH_POS)
#define HPWM_CH_3  (0x08 << HPWM_CH_POS)
#define HPWM_CH_4  (0x10 << HPWM_CH_POS)
#define HPWM_CH(param) (HPWM_CH_##param >> HPWM_CH_POS)
/*
*/
#define HPWM_OCP_HIGH   (0 << HPWM_OCP_POS)
#define HPWM_OCP_LOW    (1 << HPWM_OCP_POS)
#define HPWM_OCP(param) (HPWM_OCP_##param >> HPWM_OCP_POS)
/*
*/
#define HPWM_OCNP_HIGH   (0 << HPWM_OCNP_POS)
#define HPWM_OCNP_LOW    (1 << HPWM_OCNP_POS)
#define HPWM_OCNP(param) (HPWM_OCNP_##param >> HPWM_OCNP_POS)
/*
*/
#define HPWM_OCIDS_SET   (0 << HPWM_OCIDS_POS)
#define HPWM_OCIDS_RESET (1 << HPWM_OCIDS_POS)
#define HPWM_OCIDS(param) (HPWM_OCIDS_##param >> HPWM_OCIDS_POS)
/*
*/
#define HPWM_OCNIDS_SET   (0 << HPWM_OCNIDS_POS)
#define HPWM_OCNIDS_RESET (1 << HPWM_OCNIDS_POS)
#define HPWM_OCNIDS(param) (HPWM_OCNIDS_##param >> HPWM_OCNIDS_POS)
/*
*/
#define HPWM_CAPTRUE_FREQ (0 << HPWM_CAPTRUE_POS)
#define HPWM_CAPTRUE_FULL (1 << HPWM_CAPTRUE_POS)
#define HPWM_CAPTRUE(param) (HPWM_CAPTRUE_##param >> HPWM_CAPTRUE_POS)
/*
*/
#define HPWM_CFG_EXTRACT(cfg, name)  ((cfg >> HPWM_##name##_POS) & HPWM_##name##_MASK)
/*
*/
class HAL_PWMOut {
public:
  HAL_PWMOut() :
    timer(0),
    cfg(0),
    percent{0},
    percent100{0}
  {}
  
  HAL_Timer *timer;
  uint32_t cfg;
  float percent[4];
  int percent100[4];
  
  
  bool init(HAL_Timer *timer0, uint32_t cfg0);
  bool config(uint32_t cfg0);
  void set_percent(int index, float percent0);
  void set_percent(float *percent0);
  void set_percent100(int index, int percent0);
  void set_percent100(int *percent0);
  void set_freq(int freq);
  void set_freq_width(int freq, int width);
};

/***********************************************************
 * The user must ensure that the input frequency of PWM 
 * and the setting of timer are within the matching range.
 **********************************************************/
class HAL_PWMIn {
public:
  HAL_PWMIn() :
    timer(0),
    cfg(0),
    ch{0}
  {}
  
  HAL_Timer *timer;
  uint32_t cfg;
  uint32_t clock() {
    return timer->clock;
  }
  
  struct Channel
  {
    bool only_freq;
    bool updated;
    int width;
    int period;
    int freq;
    int freq100;
    uint32_t captrue[3];
    uint8_t index;
  }ch[4];
  
  bool init(HAL_Timer *timer0, uint32_t cfg0);
  bool config(uint32_t cfg0);
};


